package cn.pzhu.javaee.webapp.dao;

import java.lang.reflect.ParameterizedType;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.pzhu.javaee.webapp.context.WebAppContext;
import cn.pzhu.javaee.webapp.exception.WebAppSysException;



public class BaseDao<M> {	
	private final static Logger log=LoggerFactory.getLogger(BaseDao.class);
	protected DataSource ds=null;
	protected Class<M> beanClass;
	
	public BaseDao() {		
		this(WebAppContext.getWebAppContext().getDataSource());
	}
	@SuppressWarnings("unchecked")
	public BaseDao(DataSource ds) {
		super();
		this.ds = ds;		
		this.beanClass=(Class<M>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	/*
	 * 取得数据库连接
	 */
	protected Connection getConnection() throws SQLException{
		return this.ds.getConnection();
	}
	/*
	 * 取得DBUtils的QueryRunner
	 */
	protected QueryRunner getQueryRunner() throws SQLException{
		
		return new QueryRunner(this.ds);
	}
	/*
	 * 通过sql语句和sql语句中的参数读取表多个数据，并转化成Bean的List
	 */
	public List<M> list(String sql,Object...params){
		BeanListHandler<M> hander=new BeanListHandler<M>(this.beanClass);
		List<M> beanList=null;
		try {
			beanList=getQueryRunner().query(sql, hander,params);			
		} catch (SQLException e) {			
			throwWebAppSysException("读取数据库出错",e);
		}
		return beanList;
		
	}
	/*
	 * 通过sql语句和sql语句中的参数读取表一条记录，并转化成Bean
	 */
	public M get(String sql,Object...params){
		BeanHandler<M> handler=new BeanHandler<M>(this.beanClass);
		M bean=null;
		try {
			bean=getQueryRunner().query(sql, handler, params);
		} catch (SQLException e) {
			throwWebAppSysException("读取数据库出错",e);
		}
		return bean;
	}
	
	/*
	 * 取得得一个值
	 * 
	 */
	public <V> V getValue(String sql,Object...params){
		ScalarHandler<V> handler=new ScalarHandler<V>();
		V result=null;
		try {
			result=getQueryRunner().query(sql, handler, params);
		} catch (SQLException e) {
			throwWebAppSysException("读取数据库出错",e);
		}
		return result;
		
	}
	
	public boolean save(String sql,Object...params){
		boolean rFlag=false;
		try {
			rFlag=getQueryRunner().update(sql, params)==1;
		} catch (SQLException e) {
			throwWebAppSysException("写入数据出错",e);
		}
		return rFlag;
	}
	@SuppressWarnings("unchecked")
	public long getLastId(){
		BigInteger bi=this.getValue("SELECT LAST_INSERT_ID()");
		return bi.longValue();
	}
	public long update(String sql,Object...params){
		int affect=0;
		try {
			affect=getQueryRunner().update(sql, params);
		} catch (SQLException e) {
			throwWebAppSysException("更新数据出错",e);
		}
		return affect;
	}
	public long delete(String sql,Object...params){
		int affect=0;
		try {
			affect=getQueryRunner().update(sql, params);
		} catch (SQLException e) {
			throwWebAppSysException("删除数据出错",e);
		}
		return affect;
	}
	
	protected void throwWebAppSysException(String msg,Exception e){
		log.error("读取数据库出错,"+e.getMessage()+"\n========================================\n"+e.getStackTrace().toString());
		WebAppSysException sysExeption=new WebAppSysException(msg);
		throw sysExeption;
	}
	
}
